package com.hns.tool.pub;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Comparator;

import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.hns.frame.enumrate.MsgType;
import com.hns.frame.exception.BusinessException;

/**
 * FTP工具类
 * @author:yecb  
 * @email:zhuangcaijin@126.com
 * @version Revision 2.0.0
 */
public class FTPUtils {
    
    private Logger log = LoggerFactory.getLogger(this.getClass());
    
    private static FTPUtils ftp;
    /**
     * FTP服务地址
     */
    private static String ADDRESS = UtilConfig.getString("ftp_server_address");
    /**
     * FTP登录用户名
     */
    private static String USERNAME = UtilConfig.getString("ftp_server_username");
    /**
     * FTP登录密码
     */
    private static String PASSWORD = UtilConfig.getString("ftp_server_password");

    /**
     * 实例化对象
     * @return FTP工具类对象
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public static FTPUtils getInstance() {
        if (ftp == null) {
            ftp = new FTPUtils();
        }
        return ftp;
    }

    /**
     * 获取FTP客户端对象
     * @return FTP客户端对象
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public FTPClient getClient() throws Exception {
        FTPClient client = new FTPClient();
        client.setConnectTimeout(30000);// 超时设置,建议采用配置
        client.setDataTimeout(60 * 1000);// 设置数据响应超时时间默认60秒
        URL url = new URL(FTPUtils.ADDRESS);
        int port = url.getPort() < 1 ? 21 : url.getPort();
        // #测试# @jeffxu (2015-05-25)
        log.error("Ftp server listening on address " + url.toString());
        client.connect(url.getHost(), port);
        log.error("成功连接Ftp服务器...");
        client.login(FTPUtils.USERNAME, FTPUtils.PASSWORD);
        log.error("成功登录Ftp服务器...");
        // 设置为被动模式
        client.enterLocalPassiveMode();
        return client;
    }

    /**
     * 注销客户端连接
     * @param client FTP客户端对象
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    private void logout(FTPClient client) throws Exception {
        if (client != null) {
            try {
                // 有些FTP服务器未实现此功能，若未实现则会出错
                client.logout(); // 退出登录
            } catch (Exception e) {
                throw e;
            } finally {
                if (client.isConnected()) { // 断开连接
                    client.disconnect();
                }
            }
        }
    }

    /**
     * 创建目录
     * @param client FTP客户端对象
     * @param dir 目录
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public static void mkdirs(FTPClient client, String dir) throws Exception {
        if (dir == null) {
            return;
        }
        dir = dir.replace("//", "/");
        String[] dirs = dir.split("/");
        for (int i = 0; i < dirs.length; i++) {
            dir = dirs[i];
            if (!StringUtils.isEmpty(dir)) {
                if (!exists(client, dir)) {
                    client.makeDirectory(dir);
                }
                client.changeWorkingDirectory(dir);
            }
        }
    }

    /**
     * 获取FTP目录
     * @param url 原FTP目录
     * @param dir 目录
     * @return FTP目录
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public static URL getURL(URL url, String dir) throws Exception {
        String path = url.getPath();
        if (!path.endsWith("/") && !path.endsWith("//")) {
            path += "/";
        }
        dir = dir.replace("//", "/");
        if (dir.startsWith("/")) {
            dir = dir.substring(1);
        }
        path += dir;
        return new URL(url, path);
    }

    /**
     * 获取FTP目录
     * @param dir 目录
     * @return FTP目录
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public static URL getURL(String dir) throws Exception {
        return getURL(new URL(FTPUtils.ADDRESS), dir);
    }

    /**
     * 判断文件或目录是否存在
     * @param client FTP客户端对象
     * @param dir 文件或目录
     * @return 是否存在
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public static boolean exists(FTPClient client, String dir) throws Exception {
        return getFileType(client, dir) != -1;
    }

    /**
     * 判断当前为文件还是目录
     * @param client FTP客户端对象
     * @param dir 文件或目录
     * @return -1、文件或目录不存在 0、文件 1、目录
     * @throws Exception
     * @author:yecb  
     * @email:zhuangcaijin@126.com
     */
    public static int getFileType(FTPClient client, String dir) throws Exception {
        FTPFile[] files = null;
        try {
            files = client.listFiles(dir);
        } catch (Exception e) {
            return -1;
        }
        if (files.length > 1) {
            return FTPFile.DIRECTORY_TYPE;
        } else if (files.length == 1) {
            FTPFile f = files[0];
            if (f.getType() == FTPFile.DIRECTORY_TYPE) {
                return FTPFile.DIRECTORY_TYPE;
            }
            String path = dir + "/" + f.getName();
            try {
                int len = client.list(path);
                if (len == 1) {
                    return FTPFile.DIRECTORY_TYPE;
                } else {
                    return FTPFile.FILE_TYPE;
                }
            } catch (Exception e) {
                return FTPFile.FILE_TYPE;
            }
        } else {
            return -1;
        }
    }

    /**
     * 删除文件
     * @param filePath 文件的路径
     * @param dirs 文件名
     * @throws Exception
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    public static void delete(String filePath,String... dirs) throws Exception {
        if (PubUtil.isEmpty(dirs)) {
            return;
        }
        FTPClient client = null;
        try {
            client = FTPUtils.getInstance().getClient();
            client.changeWorkingDirectory(filePath);
            for (String dir : dirs) {
                    client.deleteFile(dir);
            }
        } finally {
            FTPUtils.getInstance().logout(client);
        }
    }

    /**
     * 删除目录
     * @param client FTP客户端对象
     * @param url FTP目录
     * @throws Exception
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    public static void deleteFolder(FTPClient client, URL url) throws Exception {
        // #测试# @jeffxu (2015-06-18)
        Logger log = LoggerFactory.getLogger("TestFTP");
        String path = url.getPath();
        client.changeWorkingDirectory(path);
        log.error("1、成功切换到工作目录。" + path);
        FTPFile[] files = client.listFiles();
        log.error("2、成功获取工作目录下的所有文件。" + files.length);
        String name = null;
        for (FTPFile file : files) {
            name = file.getName();
            // 排除隐藏目录
            if (".".equals(name) || "..".equals(name)) {
                continue;
            }
            if (file.getType() == FTPFile.DIRECTORY_TYPE) { // 递归删除子目录
                deleteFolder(client, getURL(url, file.getName()));
                log.error("3、成功递归删除子目录");
            } else if (file.getType() == FTPFile.FILE_TYPE) { // 删除文件
                client.deleteFile(file.getName());
                log.error("3、成功删除文件");
            }
        }
        client.changeToParentDirectory();
        log.error("4、成功切换到父级目录");
        client.removeDirectory(url.getPath());
        log.error("5、成功删除当前目录");
        // 删除当前目录
        // client.dele(url.getPath());
    }

    /**
     * 获取目录下所有文件
     * @param dir 目录
     * @return 文件名字符串
     * @throws Exception
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    //TODO
    public String[] list(String dir) throws Exception {
        FTPClient client = null;
        try {
            client = getClient();
            client.changeWorkingDirectory(dir);
            String[] values = client.listNames();
            if (values != null) {
                // 将文件排序(忽略大小写)
                Arrays.sort(values, new Comparator<String>() {
                    public int compare(String val1, String val2) {
                        return val1.compareToIgnoreCase(val2);
                    }
                });
            }
            return values;
        } catch (Exception fe) {
            // 忽略文件夹不存在的情况
            String mark = "code=550";
            if (fe.toString().indexOf(mark) == -1) {
                throw fe;
            }
        } finally {
            logout(client);
        }
        return new String[0];
    }
    
    /**
     * ftp上传
     * @param fis 上传文件流
     * @param filePath ftp上传路径
     * @param fileName 上传文件名
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    public static void ftpUpload(InputStream fis, String filePath, String fileName) throws Exception {
        // #测试# @jeffxu (2015-05-25)
        Logger log = LoggerFactory.getLogger("TestFTP");
        FTPClient ftpClient = null;
        try {
            ftpClient = FTPUtils.getInstance().getClient();
            log.error("1、成功获取Ftp连接。");
            // 设置上传目录
            ftpClient.changeWorkingDirectory(filePath);
            log.error("2、成功创建Ftp目录。");
            //ftpClient.listDirectories();
            //log.error("3、成功创建Ftp目录。");
            ftpClient.setBufferSize(1024);
            ftpClient.setControlEncoding("UTF-8");
            // 设置文件类型（二进制）
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            log.error("3、成功设置二进制文件类型。");
            ftpClient.storeFile(fileName, fis);
            log.error("4、成功保存文件。");
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(MsgType.ERROR.getFlag(), "上传有误！");
        } finally {
            IOUtils.closeQuietly(fis);
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
                throw new BusinessException(MsgType.ERROR.getFlag(), "关闭FTP连接发生异常！");
            }
        }
    }
    
    public static void main(String[] args) {
        try {
            delete("/hnsfiles/updateCenter/parmconfig/ab1bf45a9b3a4778b8cf18f516bf8e5a/", "1.txt");
            //deleteFolder(FTPUtils.getInstance().getClient(), FTPUtils.getURL("/hnsfiles/updateCenter/parmconfig/ab1bf45a9b3a4778b8cf18f516bf8e5a/"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}